function YcPromise(constructor) {
  this.status = 'pending'
  this.result = undefined
  this.collector = []
  const resolve = (res) => {
    //凝固状态，当状态发生过一次改变之后，就不会再执行以下内容了
    if (this.status !== 'pending') return;
    this.status = 'fulfilled'
    this.result = res
    /* 同步任务时，收集器中没有收集相应的执行函数，即长度为0(false)，这时候再执行收集器内的函数就会报错。所以需要在外面做一层判断，当当前实例的收集器collector中收集有相应的执行函数时，即长度不为0(true)，才执行收集器中相应的函数 */
    if (this.collector.length) {
      //异步操作时执行收集器内的函数
      this.collector.forEach(item => {
        //与逻辑短路运算的应用
        item.successCB && item.successCB(this.result)
      })
    }
  }
  const reject = (err) => {
    if (this.status !== 'pending') return;
    this.status = 'rejected'
    this.result = err
    if (this.collector.length) {
      //异步操作时执行收集器内的函数
      this.collector.forEach(item => {
        item.failCB && item.failCB(this.result)
      })
    }
  }
  constructor(resolve, reject)
}

//判断当前返回值是否是YcPromise的一个实例
function isYcPromise(returnValue, resolve, reject) {
  if (returnValue instanceof YcPromise) {
    returnValue.then(res => {
      resolve(res)
    }, err => {
      reject(err)
    })
  } else {
    resolve(returnValue)
  }
}

YcPromise.prototype.then = function (successCB, failCB) {
  return new YcPromise((resolve, reject) => {
    if (this.status === 'fulfilled') {
      //与运算符的短路运算，当左边的为假时，会立即返回false并停止执行后面的内容
      const returnValue = successCB && successCB(this.result)
      isYcPromise(returnValue, resolve, reject)
    }
    if (this.status === 'rejected') {
      const returnValue = failCB && failCB(this.result)
      isYcPromise(returnValue, resolve, reject)
    }
    /* 当当前操作为异步操作时，当前实例状态依然为pending,这时我们将传递过来的函数收集到当前实例的收集器中，当resolve或者reject方法执行的时候，再调用收集器内的函数，这样就可以解决异步问题了 */
    if (this.status === 'pending') {
      //收集器
      this.collector.push({
        successCB: () => {
          const returnValue = successCB && successCB(this.result)
          isYcPromise(returnValue, resolve, reject)
        },
        failCB: () => {
          const returnValue = failCB && failCB(this.result)
          isYcPromise(returnValue, resolve, reject)
        }
      })
    }
  })
}
